import logging
from typing import Tuple, List
import time

from src.log.logger import setup_logger
from src.model.message.messages import (
    DHTMessage, AnnouncePeerMessage, AnnouncePeerResponseMessage
)
from src.routing.routing_table import Node
from src.rpc.transation_holder import TransactionHolder

class QueryHandler:
    """DHT查询消息处理器"""

    def __init__(self, transaction_holder: TransactionHolder,unique_id:str):
        self.unique_id: str = unique_id
        self.logger: logging.Logger = setup_logger("query_handler")
        self.transaction_holder: TransactionHolder = transaction_holder
        

    def handle_query(self, data: bytes, addr: Tuple[str, int]):
        """处理查询消息"""
        try:
            message = DHTMessage.from_bytes(data=data)
            
            if message.message_type != 'q':
                return
                
            self.logger.debug(f"收到查询消息: {message.query_type} 来自: {addr}")
            
            handler = getattr(self, f"handle_{message.query_type}", None)
            if handler:
                handler(data, addr)
            else:
                self.logger.error(f"未知查询类型: {message.query_type}")
                
        except Exception as e:
            self.logger.error(f"处理查询消息失败: {e}", exc_info=True)


    async def handle_announce_peer(self, data: bytes, addr: Tuple[str, int]):
        """处理announce_peer查询
        
        Args:
            data: 查询数据
            addr: 发送方地址(ip, port)
        """
        try:
            # 解析announce_peer查询消息
            announce_message = AnnouncePeerMessage.from_bytes(data)
            self.logger.debug(f"处理announce_peer查询: {announce_message} 来自: {addr}")
            
            # 验证token
            if not self.verify_token(addr, announce_message.token):
                self.logger.warning(f"无效的token: {announce_message.token} 来自: {addr}")
                return
            
            # 更新发送方节点信息
            node = Node(
                node_id=announce_message.node_id,
                ip=addr[0],
                port=addr[1],
                last_seen=time.time()
            )
            await self.routing_table.update_node(node)
            
            # 获取实际下载端口
            download_port = addr[1] if announce_message.implied_port else announce_message.port
            
            # 记录peer信息
            self.record_peer(
                info_hash=announce_message.info_hash,
                peer_addr=(addr[0], download_port)
            )
            
            # 发送响应
            response = AnnouncePeerResponseMessage(
                transaction_id=announce_message.transaction_id,
                node_id=self.routing_table.node_id
            )
            await self.send_response(response, addr)
            
        except Exception as e:
            self.logger.error(f"处理announce_peer查询失败: {e}", exc_info=True)

    def verify_token(self, addr: Tuple[str, int], token: bytes) -> bool:
        """验证token是否有效
        
        Args:
            addr: 发送方地址
            token: 待验证的token
            
        Returns:
            bool: token是否有效
        """
        # 生成当前和前一个小时的token进行对比
        current_time = int(time.time()) // 3600
        tokens = [
            self.generate_token(addr, current_time),  # 当前小时的token
            self.generate_token(addr, current_time - 1)  # 前一小时的token
        ]
        return token in tokens

    def generate_token(self, addr: Tuple[str, int], timestamp: int) -> bytes:
        """生成token
        
        Args:
            addr: 节点地址
            timestamp: 时间戳(小时)
            
        Returns:
            bytes: 生成的token
        """
        import hashlib
        token_data = f"{addr[0]}:{timestamp}".encode()
        return hashlib.sha1(token_data).digest()[:4]

    def record_peer(self, info_hash: bytes, peer_addr: Tuple[str, int]):
        """记录peer信息
        
        Args:
            info_hash: 资源hash
            peer_addr: peer地址(ip, port)
        """
        # TODO: 实现peer信息存储逻辑
        self.logger.info(f"记录peer信息: {info_hash.hex()} -> {peer_addr}")

    @staticmethod
    def encode_nodes(nodes: List[Node]) -> bytes:
        """编码节点信息"""
        result = b''
        for node in nodes:
            result += (
                node.node_id +
                bytes(map(int, node.ip.split('.'))) +
                node.port.to_bytes(2, 'big')
            )
        return result